#pragma once

#include <boost/shared_ptr.hpp>
#include "item_id.h"
#include <typelib/types.h>
#include <typelib/fraction.h>

namespace xml { class stream; }

namespace icache {

class cache;

class footage {
public:
	virtual ~footage() { }
	virtual item_id_sptr frame_id(int frame) = 0;
	///if 'wait' is false, then the function may not return any image, but it places order
	///and requested images will be available in cache later
	virtual cached_image_sptr get(int frame, nearby may_be_requested_later = no_nearby, bool wait = true) = 0;
	///try_get(...) is much like get(... wait = false), but if image was not found in cache, footage does not request it
	virtual cached_image_sptr try_get(int frame) = 0;
	///returns pointer to cache (or cache coordinator), where frames from footage are stored
	virtual icache::cache * cache() const = 0;
public:
	///paths serialized are relative to given reference_path
	virtual xml::stream & serialize(xml::stream & s, string const & reference_path) = 0;
public:
	virtual string filepath() const = 0; ///< fullpath path to footage's file or one of footage's file
	virtual string description() const = 0;
	virtual int size() const = 0;
	virtual int first_frame_num() const = 0;
	virtual size_extent dim() const = 0;
	virtual bool alpha_channel() const = 0;
	virtual void set_deinterlace_fields(deinterlace_fields value) = 0;
	virtual deinterlace_fields get_deinterlace_fields() const = 0;
	virtual void set_deinterlace_method(deinterlace_method value) = 0;
	virtual deinterlace_method get_deinterlace_method() const = 0;
	/// returns invalid fraction if framerate is unknown (for example, for image sequences)
	virtual fraction fps() const = 0;
public:
	bool still() const { return size() == 1; }
	bool deinterlaced() const { return get_deinterlace_fields() != fields_off; }
};

struct footage_capsule {
	footage & f;
	string const & reference_path;
	footage_capsule(footage & ff, string const & rp) : f(ff), reference_path(rp) { }
};

inline xml::stream & operator || (xml::stream & s, footage_capsule & c)
	{ return c.f.serialize(s, c.reference_path); }

typedef boost::shared_ptr<footage> footage_sptr;

class footage_simple_impl : public footage {
	virtual void set_deinterlace_fields(deinterlace_fields value) { }
	virtual deinterlace_fields get_deinterlace_fields() const { return fields_off; }
	virtual void set_deinterlace_method(deinterlace_method value) { }
	virtual deinterlace_method get_deinterlace_method() const { return method_duplicate; }
};

} //namespace icache
